/**
 * @brief 配置管理模块
 * @details 主要是从配置文件中读取数据进行反序列化,得到对应的数据
 */

#pragma once

#include <iostream>
#include <string>
#include <fstream>
#include <iterator>
#include <json/json.h>

namespace hdp
{                   
    class Config
    {
    public:
        static Config &GetInstance()
        {
            static Config instance;
            return instance;
        }

        Config(const Config &) = delete;
        Config &operator=(const Config &) = delete;

    private:
        // 解析配置文件
        Config(const std::string &filename = "../config/config.json")
        {
            // Json::Reader reader;

            std::ifstream ifs(filename, std::ios::binary);
            if (!ifs.is_open())
            {
                std::cerr << "open " << filename << " failed" << std::endl;
                ifs.close();
                abort();
            }

            // 将文件内存读入字符串
            // 使用第一种方式会被解释为函数指针,需要使用括号来
            // std::string content(std::istream_iterator<char>(ifs), std::istream_iterator<char>());
            std::string content((std::istream_iterator<char>(ifs)), (std::istream_iterator<char>()));
            ifs.close();

            Json::Value root;
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            std::string err;
            bool ret = cr->parse(content.c_str(), content.c_str() + content.size(), &root, &err);
            if (ret == false)
            {
                std::cerr << "deserialize" << filename << "failed" << std::endl;
                ifs.close();
                abort();
            }

            run_mode = root["run_mode"].asBool();
            log_file = root["log_file"].asString();
            log_level = root["log_level"].asInt();
            logger_name = root["logger_name"].asString();
            log_pattern = root["log_pattern"].asString();
            buffer_size = root["buffer_size"].asInt();
            max_listen_size = root["max_listen_size"].asInt();
            block_flag = root["block_flag"].asBool();
            max_req_line = root["max_req_line"].asInt();
            timeout = root["timeout"].asInt();
            server_ip = root["server_ip"].asString();
            server_port = root["server_port"].asInt();
            thread_count = root["thread_count"].asInt();
            base_dir = root["base_dir"].asString();

            mysql_db = root["mysql_db"].asString();
            mysql_username = root["mysql_username"].asString();
            mysql_password = root["mysql_password"].asString();
            mysql_host = root["mysql_host"].asString();
            mysql_port = root["mysql_port"].asInt();

            ifs.close();
        }

    public:
        // 日志相关
        bool run_mode;           // 日志运行模式  true-发布模式； false调试模式
        std::string log_file;    // 发布模式下日志写入的文件
        int32_t log_level;       // 日志的输出等级
        std::string logger_name; // 日志输出器的名字
        std::string log_pattern; // 日志的输出格式

        // 缓冲区相关
        uint32_t buffer_size; // 默认缓冲区大小

        // 套接字相关
        int max_listen_size; // 监听的最大个数
        bool block_flag;     // 是否设置套接字非阻塞属性

        int max_req_line; // HTTP请求的最大长度
        int timeout;      // 连接超时时间

        std::string server_ip; // 服务器IP
        uint16_t server_port;  // 服务器端口号

        int thread_count;     // 线程池线程数量
        std::string base_dir; // 静态资源根目录

        // MySQL相关
        std::string mysql_db;       // MySQL数据库名
        std::string mysql_username; // 用户名
        std::string mysql_password; // 密码
        std::string mysql_host;     // MySQL服务器IP地址
        int mysql_port;             // MySQL服务器端口号
    };

}